﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Windows;

namespace Trade.Journal
{
    /// <summary>
    /// ViewRecordWindow.xaml 的交互逻辑
    /// </summary>
    public partial class ViewRecordWindow : Window
    {


        public static bool GetIsEditable(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsEditableProperty);
        }

        public static void SetIsEditable(DependencyObject obj, bool value)
        {
            obj.SetValue(IsEditableProperty, value);
        }

        // Using a DependencyProperty as the backing store for IsEditable.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsEditableProperty =
            DependencyProperty.RegisterAttached("IsEditable", typeof(bool), typeof(ViewRecordWindow), new PropertyMetadata(false));




        public ViewRecordWindow()
        {
            InitializeComponent();
        }




        private void CopyId_Click(object sender, RoutedEventArgs e)
        {
            if (DataContext is NewRecordWindowViewModel v)
                Clipboard.SetText(v.RecordId);
        }


        public void Load(Record info)
        {
            DbHelper.FillRecord(info);
            if (DataContext is ViewRecordViewModel vm)
                vm.Init(info);


            //var vm = TryFindResource("VM") as RecordWindowVM;
            //if (vm == null)
            //    return;

            //vm.RecordId = info.Id;
            //vm.Contract = info.Contract;

        }

        private void Modify_Click(object sender, RoutedEventArgs e)
        {
            // if (DataContext is NewRecordWindowViewModel v)
            //    v.IsEditable = true;
        }


        private void Underweight_Click(object sender, RoutedEventArgs e)
        {
            if (DataContext is ViewRecordViewModel v && !(v.DealRecords.LastOrDefault() is CloseDealViewModel))
            {
                v.DealRecords.Add(new UnderweightDealViewModel() { Sequence = v.DealRecords.Any() ? v.DealRecords.Max(x => x.Sequence) + 1 : 2 });
            }
        }

        private void Overweight_Click(object sender, RoutedEventArgs e)
        {
            if (DataContext is ViewRecordViewModel v)
            {
                var win = new NewRecordWindow(v.RoadMap, RelationType.Overweight, v.Contract);
                win.Owner = this;
                win.ShowDialog();
            }
        }

        private void Close_Click(object sender, RoutedEventArgs e)
        {
            if (DataContext is ViewRecordViewModel v && !(v.DealRecords.LastOrDefault() is CloseDealViewModel))
            {
                v.DealRecords.Add(new CloseDealViewModel() { Sequence = v.DealRecords.Any() ? v.DealRecords.Max(x => x.Sequence) + 1 : 1 });
            }
        }


        private void OtherTrade_Click(object sender, RoutedEventArgs e)
        {
            if (DataContext is ViewRecordViewModel v)
            {
                var win = new NewRecordWindow(v.RoadMap, RelationType.Reenter, v.Contract);  
                win.Owner = this;
                win.ShowDialog();
            }
        }

        private void ReverseTrade_Click(object sender, RoutedEventArgs e)
        {
            if (DataContext is ViewRecordViewModel v)
            {
                var win = new NewRecordWindow(v.RoadMap, RelationType.Reverse, v.Contract);
                win.Owner = this;
                win.ShowDialog();
            }
        }
         

        private void DeleteDeal_Executed(object sender, System.Windows.Input.ExecutedRoutedEventArgs e)
        {
            if (e.Parameter is DealViewModel dr && DataContext is ViewRecordViewModel v)
                v.DealRecords.Remove(dr);
        }



    }


    public partial class ViewRecordViewModel : BindableBase
    {
        public static ReleaseDirection[] ReleaseDirections { get; } = new ReleaseDirection[] { Journal.ReleaseDirection.Up, Journal.ReleaseDirection.Down };
        public static ReleaseLevel[] ReleaseLevels { get; } = new ReleaseLevel[] { Journal.ReleaseLevel.Explode, Journal.ReleaseLevel.Fast, Journal.ReleaseLevel.Normal, Journal.ReleaseLevel.Channel };

        private bool _IsEditable;

        public bool IsEditable
        {
            get { return _IsEditable; }
            set { SetProperty(ref _IsEditable, value, nameof(IsEditable), nameof(IsReadOnly)); }
        }

        public bool IsReadOnly => !IsEditable;

        public string RecordId => Record?.Id;

        private Record Record { get; set; }

        public string Contract
        {
            get { return Record?.Contract; }
            set { if (Record != null) { Record.Contract = value; NotifyPropertyChanged(); UpdateRecord(value); Multiplicator = DbHelper.QueryMultiplicator(value); } }
        }


        private RoadMap _RoadMap;

        public RoadMap RoadMap
        {
            get { return _RoadMap; }
            set { SetProperty(ref _RoadMap, value); }
        }

        private int _Multiplicator;

        public ViewRecordViewModel()
        {
            Scores.Add(new ScoreItemViewModel { Name = "总体", Value = null });
            Scores.Add(new ScoreItemViewModel { Name = "积累", Value = null });
            Scores.Add(new ScoreItemViewModel { Name = "释放", Value = null });


            DealRecords.CollectionChanged += (s, e) =>
            {
                if (e.Action == System.Collections.Specialized.NotifyCollectionChangedAction.Add)
                {
                    foreach (DealViewModel item in e.NewItems)
                    {
                        item.UpdateToDatabase = true;
                    }
                }
            };

        }

        public int Multiplicator
        {
            get { return _Multiplicator == 0 ? 10 : _Multiplicator; }
            set { SetProperty(ref _Multiplicator, value); }
        }

        public BarCycle? OpportunityCycle
        {
            get { return Record?.OpportunityCycle; }
            set { if (Record != null && value.HasValue) { Record.OpportunityCycle = value.Value; NotifyPropertyChanged(); UpdateRecord(value.Value); } }
        }

        public Opportunity Opportunity
        {
            get { return Record?.Opportunity; }
            set { if (Record != null) { Record.Opportunity = value; NotifyPropertyChanged(); UpdateRecord(value); } }
        }

        #region 释放



        public ReleaseDirection? ReleaseDirection
        {
            get { return Record?.Release?.Direction; }
            set { if (Record != null && Record.Release != null && value.HasValue) { Record.Release.Direction = value.Value; NotifyPropertyChanged(); UpdateRelease(value.Value, "Direction"); } }
        }



        public ReleaseLevel? ReleaseLevel
        {
            get { return Record?.Release?.Level; }
            set { if (Record != null && Record.Release != null && value.HasValue) { Record.Release.Level = value.Value; NotifyPropertyChanged(); UpdateRelease(value.Value, "Level"); } }
        }


        public double? ReleaseScope
        {
            get { return DefaultHandle(Record?.Release?.Scope); }
            set { if (Record != null && Record.Release != null && value.HasValue) { Record.Release.Scope = value.Value; NotifyPropertyChanged(); UpdateRelease(value.Value, "Scope"); } }
        }


        public int? ReleaseBarCount
        {
            get { return DefaultHandle(Record?.Release?.BarCount); }
            set { if (Record != null && Record.Release != null && value.HasValue) { Record.Release.BarCount = value.Value; NotifyPropertyChanged(); UpdateRelease(value.Value, "BarCount"); } }
        }


        #endregion

        #region 积累 

        public double? CumulationScope
        {
            get { return DefaultHandle(Record?.Cumulation?.Scope); }
            set { if (Record != null && Record.Cumulation != null && value.HasValue) { Record.Cumulation.Scope = value.Value; NotifyPropertyChanged(); UpdateCumulation(value.Value, "Scope"); } }
        }

        public int? CumulationBarCount
        {
            get { return DefaultHandle(Record?.Cumulation?.BarCount); }
            set { if (Record != null && Record.Cumulation != null && value.HasValue) { Record.Cumulation.BarCount = value.Value; NotifyPropertyChanged(); UpdateCumulation(value.Value, "BarCount"); } }
        }


        public CumulationType? CumulationType
        {
            get { return Record?.Cumulation?.Type; }
            set { if (Record != null && Record.Cumulation != null && value.HasValue) { Record.Cumulation.Type = value.Value; NotifyPropertyChanged(); UpdateCumulation(value.Value, "Type"); } }
        }


        #endregion 

        public double Completeness => CalcCompleteness();

        public OpenDealViewModel OpenDeal { get; set; }

        public PhotoInfo CoverPhoto { get; set; }

        public ObservableCollection<DealViewModel> DealRecords { get; } = new ObservableCollection<DealViewModel>();


        public ObservableCollection<PhotoInfo> PhotoInfos { get; } = new ObservableCollection<PhotoInfo>();

        /// <summary>
        /// 心得
        /// </summary>
        public ObservableCollection<string> Remarks { get; } = new ObservableCollection<string>();

        public ObservableCollection<string> Questions { get; } = new ObservableCollection<string>();

        /// <summary>
        /// 标签
        /// </summary>
        public ObservableCollection<string> Marks { get; } = new ObservableCollection<string>();

        public ObservableCollection<ScoreItemViewModel> Scores { get; set; } = new ObservableCollection<ScoreItemViewModel>();


        private void UpdateRecord(object v, [CallerMemberName]string sqlfield = null)
        {
            if (Record != null)
                Record.Update(v, sqlfield);
        }


        private void UpdateCumulation(object value, [CallerMemberName]string sqlfield = null)
        {
            if (Record?.Cumulation != null)
                Record.Cumulation.Update(value, sqlfield);
        }

        private void UpdateRelease(object value, [CallerMemberName]string sqlfield = null)
        {
            if (Record?.Release != null)
                Record.Release.Update(value, sqlfield);
        }


        private void SetProperty<T>(T storage, T value, [System.Runtime.CompilerServices.CallerMemberName] string propertyName = null)
        {
            //if (object.Equals(storage, value)) return false;
            if (Record == null)
                return;

            T old = storage;
            storage = value;
            OnPropertyChanged<T>(propertyName, old, value);

            if (!string.IsNullOrEmpty(propertyName))
                NotifyPropertyChanged(propertyName);

            UpdateRecord(value, propertyName);
        }

        internal void Init(Record info)
        {
            Record = info;

            RoadMap = DataShop.GetRoadmap(info.GroupId);

            OpenDeal = new OpenDealViewModel();
            OpenDeal.UpdateToDatabase = true;
            OpenDeal.DealId = info.OpenDeal.Id;
            OpenDeal.Price = info.OpenDeal.Price;
            OpenDeal.Lots = info.OpenDeal.Lots;
            OpenDeal.OpenDirection = info.OpenDeal.OpenDirection;
            // OpenDeal.Reasons = info.OpenDeal.Reasons;
            if (info.OpenDeal.Reasons != null && info.OpenDeal.Reasons.Count > 0)
                OpenDeal.Reasons.AddRange(info.OpenDeal.Reasons);
            OpenDeal.RecordId = info.OpenDeal.RecordId;
            OpenDeal.TradeCycle = info.OpenDeal.TradeCycle;
            OpenDeal.Time = info.OpenDeal.Time;


            foreach (var item in info.OpenDeal.Photos)
            {
                PhotoInfos.Add(item);
            }

            OpenDeal.PhotoSource.Source = PhotoInfos;

            foreach (var item in info.Questions)
            {
                Questions.Add(item);
            }

            foreach (var item in info.Lessons)
            {
                Remarks.Add(item);
            }

            foreach (var item in info.CloseDeals)
            {
                if (item.TradeType.HasFlag(TradeType.Additive))
                {
                    UnderweightDealViewModel val = new UnderweightDealViewModel
                    {
                        DealId = item.Id,
                        Price = item.Price,
                        Lots = item.Lots,
                        //Reasons = item.Reasons,
                        RecordId = item.RecordId,
                        Sequence = item.Sequence,
                        Time = item.Time,
                        Highest = item.Highest,
                        Lowest = item.Lowest,
                        TradeCycle = item.TradeCycle,
                        CloseType = item.CloseType,
                    };
                    if (item.Reasons != null && item.Reasons.Count != 0)
                        val.Reasons.AddRange(item.Reasons);
                    DealRecords.Add(val);
                }
                else
                {
                    var val = new CloseDealViewModel
                    {
                        DealId = item.Id,
                        Price = item.Price,
                        Lots = item.Lots,
                        //Reasons = item.Reasons,
                        RecordId = item.RecordId,
                        Sequence = item.Sequence,
                        Time = item.Time,
                        Highest = item.Highest,
                        Lowest = item.Lowest,
                        TradeCycle = item.TradeCycle,
                        CloseType = item.CloseType,
                    };
                    if (item.Reasons != null && item.Reasons.Count != 0)
                        val.Reasons.AddRange(item.Reasons);
                    DealRecords.Add(val);
                }

                DealRecords.Last().PhotoSource.Source = PhotoInfos;
            }



            foreach (var item in GetType().GetProperties())
            {
                NotifyPropertyChanged(item.Name);
            }
        }


        private T? DefaultHandle<T>(T? v) where T : struct
        {
            return v.HasValue && v.Value.Equals(default(T)) ? null : v;
        }

        private double CalcCompleteness()
        {
            double d = 0;
            if (!string.IsNullOrWhiteSpace(Contract))
                d += 5;

            //总结10
            d += Math.Min(10, Remarks.Count * 2 + CalcScore());

            //机会40
            d += 5;//周期
            if (ReleaseDirection != null)
                d += 5;
            if (ReleaseLevel != null)
                d += 5;
            if (ReleaseScope != null)
                d += 5;
            if (ReleaseBarCount != null)
                d += 5;
            if (CumulationScope != null)
                d += 5;
            if (CumulationBarCount != null)
                d += 5;



            //入场30


            //离场20

            return d / 100;
        }
        private double CalcScore()
        {
            return 0;// Scores.Sum(x => x.Value);
        }
    }


}
